package com.example.service;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.example.config.FileStorageConfig;
import com.example.utils.LogUtils;

@Service
public class FileStorageService {

    private final Path fileStorageLocation;
    private static final String LOG_TAG = "FileStorage";

    @Autowired
    public FileStorageService(FileStorageConfig fileStorageConfig) {
        this.fileStorageLocation = Paths.get(fileStorageConfig.getUploadDir())
                .toAbsolutePath().normalize();

        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (Exception ex) {
            LogUtils.error(LOG_TAG, "Could not create the directory where the uploaded files will be stored.", ex);
            throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", ex);
        }
    }

    public String storeFile(MultipartFile file, String subfolder) {
        // 规范化文件名
        String originalFileName = StringUtils.cleanPath(file.getOriginalFilename());

        try {
            // 检查文件名是否包含无效字符
            if(originalFileName.contains("..")) {
                LogUtils.error(LOG_TAG, "Filename contains invalid path sequence: " + originalFileName);
                throw new RuntimeException("Filename contains invalid path sequence " + originalFileName);
            }

            // 创建子文件夹（如果需要）
            Path targetLocation = this.fileStorageLocation;
            if (subfolder != null && !subfolder.isEmpty()) {
                targetLocation = Paths.get(this.fileStorageLocation.toString(), subfolder);
                Files.createDirectories(targetLocation);
            }

            // 生成唯一文件名
            String fileExtension = "";
            if(originalFileName.contains(".")) {
                fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
            }
            String uniqueFilename = UUID.randomUUID().toString() + fileExtension;

            // 复制文件到目标位置
            Path targetPath = targetLocation.resolve(uniqueFilename);
            Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);

            // 返回相对路径（用于存储在数据库中）
            String relativePath = subfolder != null && !subfolder.isEmpty()
                ? subfolder + "/" + uniqueFilename
                : uniqueFilename;

            LogUtils.info(LOG_TAG, "File stored successfully: " + relativePath + " (Original: " + originalFileName + ")");
            return relativePath;

        } catch (IOException ex) {
            LogUtils.error(LOG_TAG, "Could not store file " + originalFileName, ex);
            throw new RuntimeException("Could not store file " + originalFileName + ". Please try again!", ex);
        }
    }

    public Resource loadFileAsResource(String fileName) {
        try {
            Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
            Resource resource = new UrlResource(filePath.toUri());
            if(resource.exists()) {
                return resource;
            } else {
                LogUtils.error(LOG_TAG, "File not found: " + fileName);
                throw new RuntimeException("File not found " + fileName);
            }
        } catch (MalformedURLException ex) {
            LogUtils.error(LOG_TAG, "File not found: " + fileName, ex);
            throw new RuntimeException("File not found " + fileName, ex);
        }
    }
    
    /**
     * 删除文件
     * @param filePath 相对于存储根目录的文件路径
     * @return 是否删除成功
     */
    public boolean deleteFile(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            LogUtils.warn(LOG_TAG, "Attempted to delete file with empty path");
            return false;
        }
        
        try {
            // 从URL路径转换为文件系统路径
            // 如果路径是 /users/avatars/xxx.jpg 格式，需要去掉前缀
            String normalizedPath = filePath;
            if (normalizedPath.startsWith("/users/avatars/")) {
                normalizedPath = "avatars/" + normalizedPath.substring("/users/avatars/".length());
            }
            
            Path targetPath = this.fileStorageLocation.resolve(normalizedPath).normalize();
            
            // 安全检查 - 确保目标文件在存储目录内
            if (!targetPath.startsWith(this.fileStorageLocation)) {
                LogUtils.error(LOG_TAG, "Security violation: Attempted to delete file outside storage directory: " + filePath);
                return false;
            }
            
            if (Files.exists(targetPath)) {
                Files.delete(targetPath);
                LogUtils.info(LOG_TAG, "File deleted successfully: " + filePath);
                return true;
            } else {
                LogUtils.warn(LOG_TAG, "File not found for deletion: " + filePath);
                return false;
            }
        } catch (IOException ex) {
            LogUtils.error(LOG_TAG, "Error deleting file: " + filePath, ex);
            return false;
        }
    }
}